export interface TBeat {
  ping: () => boolean;
  pong: (data: any) => boolean;
};

export class Heartbeat {
  private interval = 3000;
  private timeout = 1500;
  private sendTime = 0;

  private intervalId = 0;
  private timeoutId = 0;

  public onDelayChange: undefined | ((delay: number) => void);
  public onRetry: undefined | (() => void);

  public constructor(private beat: TBeat, interval = 3000, timeout = 1500) {
    this.interval = interval;
    this.timeout = timeout;
  }

  public start() {
    clearInterval(this.intervalId);
    clearTimeout(this.timeoutId);

    this.intervalId = window.setInterval(() => {
      this.sendTime = Date.now();
      this.beat.ping();
      // console.time('❤️');

      this.timeoutId = window.setTimeout(() => {
        if (this.sendTime !== 0) {
          this.stop();
          this.onRetry?.();
        }
      }, this.timeout);
    }, this.interval);
  }

  public stop() {
    clearInterval(this.intervalId);
    clearTimeout(this.timeoutId);
    this.sendTime = 0;
    // console.timeEnd('❤️');
  }

  public pong(data: any) {
    if (this.beat.pong(data)) {
      // console.timeEnd('❤️');
      this.onDelayChange?.(Date.now() - this.sendTime);
      this.sendTime = 0;
      clearTimeout(this.timeoutId);
    }
  }
}
